using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using OpenComposite.Properties;


namespace OpenComposite.Base.Designer
{
	/// <summary>
	/// Base class for DesignerControls.
	/// </summary>
	[TypeConverter(typeof(ExpandableObjectConverter)), System.Runtime.InteropServices.GuidAttribute("71C10F2F-6E9B-4085-899E-18B9FD9C53F9")]
	public class DesignerControl
		: IDisposable, IXmlSerializable, ICloneable, IDropControl, IDragControl, IServiceProvider, IEquatable<Route>
	{
		#region Initialization
		/// <summary>
		/// Initialize a new instance of DesignerControl.
		/// </summary>
		public DesignerControl()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			guidIdentifier = Guid.NewGuid();

			// initialize private variables
			_bEnabled = true;
			_bSelected = false;
			_bFocused = false;
			_bTabStop = true;
			_bVisible = true;
			_bAllowDrop = true;
			_bIsDisposed = false;
			_bTopLevel = false;
			bMouseOver = false;
			bMouseOverChild = false;
			_contextMenu = null;
			_controls = new DesignerControlCollection(this);
			_cursor = Cursors.Default;
			_cursorBeforeOver = null;
			_designerView = null;
			_maxSize = Size.Empty;
			_minSize = Size.Empty;
			_iTabIndex = 0;
			_name = getDefaultName(); // old: "designerControl" + GetCount(typeof(DesignerControl));
			_parent = null;
			_bounds = new Rectangle(0, 0, 20, 20);
			_boundsPaint = new Rectangle(0, 0, 20, 20);
			_boundsMouse = new Rectangle(0, 0, 20, 20);
			_tag = null;
			_text = _name;
			_selectionFrame = null;
			_anchor = AnchorStyles.Top | AnchorStyles.Left;
			_site = null;
			_ptMouseDown = Point.Empty;
			_toolTip = null;

			this.BackColor = Color.White;
			this.Font = new Font("Tahoma", 8.25f);
			this.ForeColor = Color.Black;

			//
			// ContextMenuStrip
			//
			this.ContextMenuStrip = new ContextMenuStrip();
			this.ContextMenuStrip.Items.Add("Remove", Resources.png_delete,
											new EventHandler(context_Remove));

			this.EndUpdate();
		}
		#endregion

		#region Static Members

		private static Dictionary<Type, int> _dicCounter = new Dictionary<Type, int>();
		public static string GetCount(Type type)
		{
			int count = 0;
			if ( _dicCounter.ContainsKey(type) ) {
				count = _dicCounter[type];
				count++;
				_dicCounter[type] = count;
			} else {
				count++;
				_dicCounter.Add(type, count);
			}
			return count.ToString();
		}

		#endregion

		#region Public Members

		#region Properties

		/// <summary>
		/// Unique identifer of this DesignerControl.
		/// </summary>
		public Guid Identifier
		{
			get { return guidIdentifier; }
		}

		/// <summary>
		/// Gets the bounds of control.
		/// </summary>
		public Rectangle Bounds
		{
			get
			{
				return _bounds;
			}
			set
			{
				SetBounds(value.X, value.Y, value.Width, value.Height, BoundsSpecified.All);
			}
		}
		/// <summary>
		/// Gets the client rectangle of the control.
		/// </summary>
		public Rectangle ClientRectangle
		{
			get
			{
				Rectangle r = CalculateClientArea();
				return new Rectangle(0, 0, r.Width, r.Height);
			}
		}
		/// <summary>
		/// Gets the rectangle that represents the virtual display area of the control.
		/// </summary>
		public Rectangle DisplayRectangle
		{
			get
			{
				return new Rectangle(0, 0, _bounds.Width, _bounds.Height);
			}
		}

		/// <summary>
		/// Gets or sets the coordinates of the upper-left corner of the control
		/// relative to the upper-left corner of its container.
		/// </summary>
		public Point Location
		{
			get
			{
				return _bounds.Location;
			}
			set
			{
				SetBounds(value.X, value.Y, 0, 0, BoundsSpecified.Location);
			}
		}
		/// <summary>
		/// Gets or sets the height and width of the control.
		/// </summary>
		public Size Size
		{
			get
			{
				return _bounds.Size;
			}
			set
			{
				SetBounds(0, 0, value.Width, value.Height, BoundsSpecified.Size);
			}
		}

		/// <summary>
		/// Gets or sets the edges of the container to which a control is bound and
		/// determines how a control is resized with its parent. 
		/// </summary>
		public AnchorStyles Anchor
		{
			get { return _anchor; }
			set
			{
				_anchor = value;
				doAnchorChanged();
			}
		}

		/// <summary>
		/// Gets or sets the distance, in pixels, between the top edge of the control and
		/// the top edge of its container's client area.
		/// </summary>
		public int Top
		{
			get
			{
				return _bounds.Top;
			}
			set
			{
				SetBounds(0, value, 0, 0, BoundsSpecified.Y);
			}
		}
		/// <summary>
		/// Gets the distance, in pixels, between the bottom edge of the control and
		/// the top edge of its container's client area.
		/// </summary>
		public int Bottom
		{
			get
			{
				return _bounds.Bottom;
			}
		}
		/// <summary>
		/// Gets or sets the distance, in pixels, between the left edge of the control and
		/// the left edge of its container's client area.
		/// </summary>
		public int Left
		{
			get
			{
				return _bounds.Left;
			}
			set
			{
				SetBounds(value, 0, 0, 0, BoundsSpecified.X);
			}
		}
		/// <summary>
		/// Gets the distance, in pixels, between the right edge of the control and
		/// the left edge of its container's client area.
		/// </summary>
		public int Right
		{
			get
			{
				return _bounds.Right;
			}
		}
		/// <summary>
		/// Gets or sets the width of the control.
		/// </summary>
		public int Width
		{
			get
			{
				return _bounds.Width;
			}
			set
			{
				SetBounds(0, 0, value, 0, BoundsSpecified.Width);
			}
		}
		/// <summary>
		/// Gets or sets the height of the control.
		/// </summary>
		public int Height
		{
			get
			{
				return _bounds.Height;
			}
			set
			{
				SetBounds(0, 0, 0, value, BoundsSpecified.Height);
			}
		}

		/// <summary>
		/// Gets or sets the size that is the upper limit of the DesignerControls size.
		/// </summary>
		public virtual Size MaximumSize
		{
			get
			{
				return _maxSize;
			}
			set
			{
				bool changed = false;
				if ( _maxSize != value )
					changed = true;
				_maxSize = value;
				if ( changed )
					doMaxSizeChanged();
			}
		}
		/// <summary>
		/// Gets or sets the size that is the lower limit of the DesignerControls size.
		/// </summary>
		public virtual Size MinimumSize
		{
			get
			{
				return _minSize;
			}
			set
			{
				bool changed = false;
				if ( _minSize != value )
					changed = true;
				_minSize = value;
				if ( changed )
					doMinSizeChanged();
			}
		}
		/// <summary>
		/// Gets the size of a rectangular area into which the control can fit.
		/// </summary>
		public Size PreferredSize
		{
			get
			{
				return _bounds.Size;
			}
		}

		public ToolTip Tooltip
		{
			get { return _toolTip; }
			protected set { _toolTip = value; }
		}
		public virtual string ToolText { get; protected set; }

		public bool TopLevel
		{
			get { return _bTopLevel; }
			set
			{
				if ( _bTopLevel != value ) {
					_bTopLevel = value;
					Repaint();
				}
			}
		}

		public virtual bool CanSelect
		{
			get { return false; }
		}
		public virtual bool CanFocused
		{
			get { return false; }
		}
		public virtual bool CanMove
		{
			get { return false; }
		}
		public virtual bool CanResize
		{
			get { return true; }
		}

		public virtual bool CanDrag
		{
			get { return true; }
		}

		public virtual ResizeSides ResizableSides
		{
			get { return ResizeSides.All; }
		}
		public virtual bool IsContainer
		{
			get { return false; }
		}
		public virtual bool NoClip
		{
			get { return false; }
		}

		public virtual bool UseGrid
		{
			get { return false; }
		}
		public virtual SizeF GridOffset
		{
			get { return SizeF.Empty; }
		}


		public bool ContainsSelected
		{
			get
			{
				foreach ( DesignerControl ctrl in this.Controls ) {
					if ( ctrl.Selected || ctrl.ContainsSelected )
						return true;
				}
				return false;
			}
		}

		public bool Enabled
		{
			get
			{
				return _bEnabled;
			}
			set
			{
				_bEnabled = value;
				Repaint();
			}
		}
		public bool Selected
		{
			get
			{
				return _bSelected;
			}
			set
			{
				if ( !this.CanSelect ) {
					_bSelected = false;
					doSelectionChanged();
				} else if ( _bSelected != value ) {
					_bSelected = value;
					doSelectionChanged();
				}
			}
		}
		public bool Focused
		{
			get
			{
				return _bFocused;
			}
		}
		public bool Visible
		{
			get
			{
				return _bVisible;
			}
			set
			{
				_bVisible = value;
				OnVisibleChanged();
				Repaint();
			}
		}

		/// <summary>
		/// Gets or Sets the ContextMenuStrip for this control that appears on a right click.
		/// </summary>
		public ContextMenuStrip ContextMenuStrip
		{
			get
			{
				return _contextMenu;
			}
			set
			{
				_contextMenu = value;
			}
		}

		public bool HasChildren
		{
			get
			{
				return ( _controls.Count > 0 );
			}
		}
		public DesignerControlCollection Controls
		{
			get
			{
				return _controls;
			}
		}
		[XmlIgnore]
		public DesignerControl Parent
		{
			get
			{
				return _parent;
			}
			set
			{
				// parent value changed
				if ( _parent != value ) {
					// release events and remove this from child list of the old parent
					releaseParent();
					// set the new parent
					_parent = value;
					// register events and add this to child list of the new parent
					doParentChanged();
				}
			}
		}
		[XmlIgnore]
		public DesignerViewControl DesignerViewControl
		{
			get
			{
				return _designerView;
			}
			set
			{
				if ( _designerView != value ) {
					releaseDesignerView();
					_designerView = value;
					doDesignerViewChanged();
				}
			}
		}

		[XmlIgnore]
		public Cursor Cursor
		{
			get
			{
				return _cursor;
			}
			set
			{
				_cursor = value;
			}
		}

		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}
		public object Tag
		{
			get
			{
				return _tag;
			}
			set
			{
				_tag = value;
			}
		}

		[XmlIgnore]
		public virtual Color BackColor
		{
			get
			{
				return _backColor1;
			}
			set
			{
				if ( _backColor1 != value ) {
					_backColor1 = value;
					doBackColor1Changed();
				}
			}
		}
		[XmlIgnore]
		public Color ForeColor
		{
			get
			{
				if ( _foreSolidBrush == null )
					_foreSolidBrush = new SolidBrush(Color.Black);
				return _foreSolidBrush.Color;
			}
			set
			{
				if ( _foreSolidBrush == null )
					_foreSolidBrush = new SolidBrush(Color.Black);
				if ( _foreSolidBrush.Color != value ) {
					_foreSolidBrush.Color = value;
					doForeColorChanged();
				}
			}
		}
		[XmlIgnore]
		public Font Font
		{
			get
			{
				return _font;
			}
			set
			{
				_font = value;
				doFontChanged();
			}
		}
		public virtual string Text
		{
			get
			{
				return _text;
			}
			set
			{
				_text = value;
				doTextChanged();
			}
		}

		public int TabIndex
		{
			get
			{
				return _iTabIndex;
			}
			set
			{
				_iTabIndex = value;
				doTabIndexChanged();
			}
		}
		public bool TabStop
		{
			get
			{
				return _bTabStop;
			}
			set
			{
				_bTabStop = value;
			}
		}

		public bool AllowDrop
		{
			get { return _bAllowDrop; }
			set { _bAllowDrop = value; }
		}

		public bool IsDisposed
		{
			get { return _bIsDisposed; }
		}

		public string Mode
		{
			get
			{
				if ( this.DesignerViewControl != null && this.DesignerViewControl.DesignController != null ) {
					return ( this.DesignerViewControl.DesignController.Mode != null ?
						this.DesignerViewControl.DesignController.Mode : "Undefined" );
				} else {
					return "Undefined";
				}
			}
		}

		/// <summary>
		/// Gets or sets the site of the control.
		/// </summary>
		public virtual ISite Site
		{
			get { return _site; }
			set
			{
				if ( _site != value ) {
					_site = value;
					foreach ( DesignerControl dc in this.Controls ) {
						dc.Site = _site;
					}
				}
			}
		}
		#endregion

		#region Events

		/// <summary>
		/// Occurs when the Text property value changes.
		/// </summary>
		public event EventHandler TextChanged = null;
		/// <summary>
		/// Occurs when the Location property value changes.
		/// </summary>
		public event EventHandler LocationChanged = null;
		/// <summary>
		/// Occurs when the Size property value changes.
		/// </summary>
		public event EventHandler SizeChanged = null;
		/// <summary>
		/// Occurs when the Parent property value changes.
		/// </summary>
		public event EventHandler ParentChanged = null;
		/// <summary>
		/// Occurs when the DesignerView property value changes.
		/// </summary>
		public event EventHandler DesignerViewChanged = null;

		/// <summary>
		/// Occurs when the control receives focus.
		/// </summary>
		public event EventHandler GotFocus = null;
		/// <summary>
		/// Occurs when the control loses focus.
		/// </summary>
		public event EventHandler LostFocus = null;

		/// <summary>
		/// Occurs when the BackColor property value changes.
		/// </summary>
		public event EventHandler BackColorChanged = null;

		/// <summary>
		/// Occurs when the PaintBounds changes.
		/// </summary>
		public event EventHandler PaintBoundsChanged = null;

		/// <summary>
		/// Occurs before a DesignerControl is removed.
		/// </summary>
		public event CancelEventHandler Removing = null;
		/// <summary>
		/// Occurs after a DesignerControl was removed
		/// </summary>
		public event EventHandler Removed = null;
		/// <summary>
		/// Occurs when the DesignerControl is disposed by a call to the Dispose method.
		/// </summary>
		public event EventHandler Disposed = null;

		// Mouse Events
		/// <summary>
		/// Occurs when the mouse pointer enters the control.
		/// </summary>
		public event EventHandler MouseEnter = null;
		/// <summary>
		/// Occurs when the mouse pointer is moved over the control.
		/// </summary>
		public event MouseEventHandler MouseMove = null;
		/// <summary>
		/// Occurs when the mouse pointer is over the control and a mouse button is pressed.
		/// </summary>
		public event MouseEventHandler MouseDown = null;
		/// <summary>
		/// Occurs when the mouse pointer is over the control and a mouse button is released.
		/// </summary>
		public event MouseEventHandler MouseUp = null;
		/// <summary>
		/// Occurs when the control is clicked by the mouse.
		/// </summary>
		public event MouseEventHandler MouseClick = null;
		/// <summary>
		/// Occurs when the control is double clicked by the mouse.
		/// </summary>
		public event MouseEventHandler MouseDoubleClick = null;
		/// <summary>
		/// Occurs when the mouse pointer leaves the control.
		/// </summary>
		public event EventHandler MouseLeave = null;

		#endregion

		#region Methods
		public bool Focus()
		{
			if ( !this.CanFocused ) {
				_bFocused = false;
				return false;
			}
			bool bSuccess = false;
			if ( _bFocused )
				bSuccess = true;
			else if ( this.DesignerViewControl != null ) {
				this.BeginUpdate();
				_bFocused = true;
				this.DesignerViewControl.Status.FocusedContol = this;
				bSuccess = true;
				OnGotFocus(EventArgs.Empty);
				this.EndUpdate();
			}
			return bSuccess;
		}
		public void Select()
		{
			this.Selected = true;
		}

		public void Hide()
		{
			this.Visible = false;
		}
		public void Show()
		{
			this.Visible = true;
		}
		/// <summary>
		/// Remove the control from the parent container
		/// </summary>
		public void Remove()
		{
			this.BeginUpdate();
			CancelEventArgs ce = new CancelEventArgs(false);
			OnRemoving(ce);
			if ( ce.Cancel ) {
				this.EndUpdate();
				return;
			}
			if ( this.Status != null ) {
				if ( this.Status.CaptureControl == this ) this.Status.CaptureControl = null;
				if ( this.Status.DragObject == this ) this.Status.DragObject = null;
				if ( this.Status.FocusedContol == this ) this.Status.FocusedContol = null;
				if ( this.Status.MouseOverCtrl == this ) this.Status.MouseOverCtrl = null;
			}
			if ( this.IsContainer ) {
				while ( this.Controls.Count > 0 ) {
					this.Controls[0].Remove();
				}
			}
			if ( this.Parent != null && this.Parent.Controls.Contains(this) ) {
				this.Parent.Controls.Remove(this);
			}
			if ( this.DesignerViewControl != null ) {
				// remove selection of this control
				this.Selected = false;
				// remove this control from the designer view
				if ( this.DesignerViewControl.DesignerControls.Contains(this) ) {
					this.DesignerViewControl.DesignerControls.Remove(this);
				}
			}

			this.Hide();
			this.Dispose();
			OnRemoved(EventArgs.Empty);
			this.EndUpdate();
			this.DesignerViewControl = null;
		}

		public void Invalidate()
		{
			if ( this.DesignerViewControl != null ) {
				Rectangle ri = this.GetPaintBounds();
				ri.Inflate(10, 10);
				ri = ApplyZoomFactor(ri);
				this.DesignerViewControl.MainPanel.Invalidate(ri, true);
				foreach ( DesignerControl dc in this.Controls ) {
					dc.Invalidate();
				}
			}
		}
		public void Refresh()
		{
			Repaint();
		}
		public void Update()
		{
			if ( this.DesignerViewControl != null ) {
				this.DesignerViewControl.Refresh();
			}
		}

		public void BringToFront()
		{
			if ( this.Parent != null ) {
				DesignerControl parent = this.Parent;
				parent.Controls.Remove(this);
				parent.Controls.Add(this);
			} else if ( this.DesignerViewControl != null ) {
				DesignerViewControl dvc = this.DesignerViewControl;
				dvc.DesignerControls.Remove(this);
				dvc.DesignerControls.Add(this);
			}
		}
		public void SendToBack()
		{
			if ( this.Parent != null ) {
				this.Parent.Controls.Remove(this);
				this.Parent.Controls.Insert(0, this);
			} else if ( this.DesignerViewControl != null ) {
				this.DesignerViewControl.DesignerControls.Remove(this);
				this.DesignerViewControl.DesignerControls.Insert(0, this);
			}
		}

		/// <summary>
		/// Convert a point from client area coordinates of this control to screen coordinates
		/// </summary>
		public Point PointToDesignerView(Point p)
		{
			Rectangle rectClient = CalculateClientArea();
			p.Offset(rectClient.Location);
			if ( this.Parent == null )
				return p;
			else {
				return this.Parent.PointToDesignerView(p);
			}
		}
		/// <summary>
		/// Convert a rectangle from client area coordinates of this control to screen coordinates
		/// </summary>
		/// <param name="r">A Rectangle.</param>
		public Rectangle RectangleToDesignerView(Rectangle r)
		{
			Rectangle rectClient = CalculateClientArea();
			r.Offset(rectClient.Location);
			if ( this.Parent == null )
				return r;
			else {
				return this.Parent.RectangleToDesignerView(r);
			}
		}

		/// <summary>
		/// Convert a point from screen coordinates to client area coordinates of this control
		/// </summary>
		public Point PointToDesignerControlClient(Point p)
		{
			Rectangle rectClient = this.GetPaintClientArea();
			p.Offset(-rectClient.X, -rectClient.Y);
			return p;
		}
		/// <summary>
		/// Convert a rectangle from screen coordinates to client area coordinates of this control
		/// </summary>
		public Rectangle RectangleToDesignerControlClient(Rectangle r)
		{
			Rectangle rectClient = this.GetPaintClientArea();
			r.Offset(-rectClient.X, -rectClient.Y);
			return r;
		}

		/// <summary>
		/// Suspend Repaint.
		/// </summary>
		public void BeginUpdate()
		{
			lock ( lockAll ) {
				if ( this.DesignerViewControl != null )
					this.DesignerViewControl.BeginUpdate();
			}
		}
		/// <summary>
		/// Resume Repaint.
		/// </summary>
		public void EndUpdate()
		{
			lock ( lockAll ) {
				if ( this.DesignerViewControl != null )
					this.DesignerViewControl.EndUpdate();
			}
		}

		/// <summary>
		/// Paint the background of the DesignerControl.
		/// </summary>
		/// <param name="pe">PaintEventArgs.</param>
		public virtual void PaintBackground(PaintEventArgs pe)
		{
		}
		/// <summary>
		/// Paint the Designer Control.
		/// </summary>
		/// <param name="pe">PaintEventArgs.</param>
		public virtual void Paint(PaintEventArgs pe)
		{
			if ( !this.Visible )
				return;

			PaintChildControls(pe);

			#region Paint Bounds (Disabled)
			//pe.Graphics.DrawRectangle(Pens.Orange, RectangleToDesignerView(this.DisplayRectangle));
			//if ( this.Parent != null )
			//    pe.Graphics.DrawRectangle(Pens.LightGreen, this.Parent.RectangleToDesignerView(this.Bounds));
			//else
			//    pe.Graphics.DrawRectangle(Pens.LightGreen, this.Bounds);
			#endregion
		}

		public virtual object GetDragObject(Point location, MouseButtons button)
		{
			if ( this.Parent != null )
				return this.Parent.GetDragObject(location, button);
			else
				return this;
		}
		public virtual void DropObject(object obj, Point location, MouseButtons button)
		{
			if ( this.Parent != null )
				this.Parent.DropObject(obj, location, button);
		}
		public virtual bool IsDropAllowed(object obj, Point location, MouseButtons button)
		{
			if ( this.AllowDrop && this.Parent != null )
				return this.Parent.IsDropAllowed(obj, location, button);
			else
				return false;
		}
		public virtual bool IsDropAllowed(Type type, Point location, MouseButtons button)
		{
			if ( this.AllowDrop && this.Parent != null )
				return this.Parent.IsDropAllowed(type, location, button);
			else
				return false;
		}

		public override string ToString()
		{
			return string.Format("{0} {{ Location: {1}; Size: {2} }}", this.Text, this.Location, this.Size);
		}

		public virtual Rectangle GetPaintBounds()
		{
			Rectangle rectPaint;
			if ( this.Parent == null || this.Parent is Route )
				rectPaint = this.Bounds;
			else
				rectPaint = this.Parent.RectangleToDesignerView(this.Bounds);
			return rectPaint;
		}

		/// <summary>
		/// Retrieves the child control that is located at the specified coordinates.
		/// </summary>
		/// <param name="location">A Point that contains the coordinates where you want to look for a control. 
		/// Coordinates are expressed relative to the upper-left corner of the control's client area.</param>
		/// <returns>A Control that represents the control that is located at the specified point. </returns>
		public DesignerControl GetChildAtPoint(Point location)
		{
			if ( this.Visible ) {
				for ( int i = this.Controls.Count - 1; i >= 0; i-- ) {
					if ( this.Controls[i].Visible && this.Controls[i].Bounds.Contains(location) )
						return this.Controls[i];
				}
			}
			return null;
		}
		public virtual bool CheckMouseOver(Point location)
		{
			bool bOver = false;
			if ( this.Visible && this.Enabled ) {
				using ( Region region = GetMouseOverArea() ) {
					bOver = ( this.Visible && region.IsVisible(location) );
				}
			}
			return bOver;
		}

		public DesignerControl[] GetPredecessors()
		{
			if ( this.DesignerViewControl == null )
				return new DesignerControl[0];

			List<DesignerControl> list = new List<DesignerControl>();
			Route[] routes = this.DesignerViewControl.GetRoutesEndToStart(this);
			foreach ( Route r in routes ) {
				list.Add(r.StartControl);
			}
			return list.ToArray();
		}
		public DesignerControl[] GetSuccessors()
		{
			if ( this.DesignerViewControl == null )
				return new DesignerControl[0];

			List<DesignerControl> list = new List<DesignerControl>();
			Route[] routes = this.DesignerViewControl.GetRoutesStartToEnd(this);
			foreach ( Route r in routes ) {
				list.Add(r.EndControl);
			}
			return list.ToArray();
		}

		/// <summary>
		/// Initialize a new DesignerControl (e.g. created by drag'n'drop from the toolbox).
		/// </summary>
		public virtual void InitializeNew(IServiceProvider serviceProvider)
		{
		}
		/// <summary>
		/// Initialize a loaded DesignerControl
		/// </summary>
		public virtual void InitializeLoaded()
		{
		}

		#endregion

		#region IDisposable Members

		public virtual void Dispose()
		{
			try {
				dispose(_backSolidBrush);
				dispose(_foreSolidBrush);

				foreach ( DesignerControl ctrl in this.Controls ) {
					ctrl.Dispose();
				}
				this.Controls.Clear();
			} finally {
				_bIsDisposed = true;
				EventHandler tmp = this.Disposed;
				if ( tmp != null )
					tmp(this, EventArgs.Empty);
			}
		}

		#endregion

		#region IXmlSerializable Members

		public virtual XmlSchema GetSchema()
		{
			return null;
		}

		public virtual void ReadXml(XmlReader reader)
		{
			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControls":
						// read child controls
						ReadChildControls(reader);
						break;
					default:
						// read standard properties
						ReadStandardProperties(reader);
						break;
				}
			}
		}
		/// <summary>
		/// Read and Set the standard properties of this DesignerControl (ID, Name, Text, Bounds). 
		/// Call this methods in a while loop: 
		/// while ( reader.Read() ) { switch ( reader.Name ) { ... default: ReadStandardProperties(reader); break; } }
		/// </summary>
		/// <param name="reader">The XmlReader of ReadXml.</param>
		protected virtual void ReadStandardProperties(XmlReader reader)
		{
			switch ( reader.Name ) {
				case "ID":
					this.guidIdentifier = new Guid(reader.ReadString());
					break;
				case "Name":
					this.Name = reader.ReadString();
					break;
				case "Text":
					this.Text = reader.ReadString();
					break;
				case "Bounds":
					RectangleConverter rc = new RectangleConverter();

					string s = reader.ReadString();
					this.Bounds = (Rectangle)rc.ConvertFromString(null, CultureInfo.InvariantCulture, s.Replace(';', ','));
					break;
				case "Anchor":
					this.Anchor = (AnchorStyles)Enum.Parse(typeof(AnchorStyles), reader.ReadString());
					break;
				case "Visible":
					BooleanConverter bc = new BooleanConverter();
					this.Visible = (bool)bc.ConvertFromString(reader.ReadString());
					break;
			}
		}
		/// <summary>
		/// Read and Add the child controls of this DesignerControl. 
		/// Call this methods in a while loop: 
		/// while ( reader.Read() ) { switch ( reader.Name ) { ... case "DesignerControls": { ReadChildControls(reader); break; } } }
		/// </summary>
		/// <param name="reader">The XmlReader of ReadXml.</param>
		protected virtual void ReadChildControls(XmlReader reader)
		{
			if ( reader.IsEmptyElement || reader.NodeType == XmlNodeType.EndElement )
				return;

			while ( reader.Read() ) {
				switch ( reader.Name ) {
					case "DesignerControls":
						if ( reader.NodeType == XmlNodeType.EndElement )
							return;
						break;
					case "DesignerControl":
						if ( reader.NodeType == XmlNodeType.Element ) {
							string typename = reader.GetAttribute("Type");
							AddSerializedDesignerControl(typename, reader);
						}
						break;
				}
			}
		}
		/// <summary>
		/// Create a new instance of the Type typename, deserialize the xml and add the new control to the Controls collection.
		/// </summary>
		/// <param name="typename">Type name of the new DesignerControl.</param>
		/// <param name="reader">XmlReader that contains the serialized Xml data.</param>
		protected DesignerControl AddSerializedDesignerControl(string typename, XmlReader reader)
		{
			return AddSerializedDesignerControl(typename, reader, true);
		}
		/// <summary>
		/// Create a new instance of the Type typename, deserialize the xml and add the new control to the Controls collection.
		/// </summary>
		/// <param name="typename">Type name of the new DesignerControl.</param>
		/// <param name="reader">XmlReader that contains the serialized Xml data.</param>
		protected DesignerControl AddSerializedDesignerControl(string typename, XmlReader reader, bool addToControl)
		{
			DesignerControl dctrl = null;
			Type type = null;
			Type[] types = null;
			try {
				if ( this.DesignerViewControl != null ) {
					types = this.DesignerViewControl.Types;
				} else if ( this.Site != null ) {
					OpenComposite.Base.Designer.DesignerViewControl dvc = this.Site.Component as DesignerViewControl;
					if ( dvc != null ) {
						types = dvc.Types;
					}
				}
				if ( types != null ) {
					foreach ( Type t in types ) {
						if ( t.FullName == typename ) {
							type = t;
							break;
						}
					}
				}
				if ( type == null ) {
					type = Type.GetType(typename);
				}
			} catch {
				type = null;
			}
			if ( type != null ) {
				System.Reflection.ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
				object obj = ctor.Invoke(new object[0]);
				//object obj = type.TypeInitializer.Invoke(new object[0]);
				if ( obj is IXmlSerializable ) {
					if ( obj is DesignerControl ) {
						dctrl = (DesignerControl)obj;
						this.Controls.Add(dctrl);
					}
					( (IXmlSerializable)obj ).ReadXml(reader);
				}
			}
			return dctrl;
		}

		public virtual void WriteXml(XmlWriter writer)
		{
			WriteStandardProperties(writer);
			WriteChildControls(writer);
		}
		protected virtual void WriteStandardProperties(XmlWriter writer)
		{
			RectangleConverter rc = new RectangleConverter();
			BooleanConverter bc = new BooleanConverter();

			writer.WriteAttributeString("Type", this.GetType().ToString());

			writer.WriteElementString("ID", this.Identifier.ToString());
			writer.WriteElementString("Name", this.Name);
			writer.WriteElementString("Text", this.Text);
			writer.WriteElementString("Bounds", rc.ConvertToString(null, CultureInfo.InvariantCulture, this.Bounds));
			writer.WriteElementString("Anchor", ( (int)this.Anchor ).ToString());
			writer.WriteElementString("Visible", bc.ConvertToString(this.Visible));
		}
		protected virtual void WriteChildControls(XmlWriter writer)
		{
			bool controlsStartAdded = false;
			if ( this.IsContainer && this.Controls.Count > 0 ) {
				foreach ( DesignerControl dc in this.Controls ) {
					if ( dc is ListView || dc is Button || dc is TextBox || dc is ComboBox )
						continue;
					if ( !controlsStartAdded ) {
						writer.WriteStartElement("DesignerControls");
						controlsStartAdded = true;
					}
					writer.WriteStartElement("DesignerControl");
					dc.WriteXml(writer);
					writer.WriteEndElement();
				}
				if ( controlsStartAdded ) {
					writer.WriteEndElement();
				}
			}
		}

		#endregion

		#region ICloneable Members

		public object Clone()
		{
			return this.MemberwiseClone();
		}

		#endregion

		#region IServiceProvider Members

		public virtual object GetService(Type serviceType)
		{
			if ( this.Site != null )
				return this.Site.GetService(serviceType);
			else
				return null;
		}

		#endregion

		#endregion

		#region Internal Members

		internal delegate void DelegatePaintBoundsChanged();
		internal DelegatePaintBoundsChanged ChildPaintBoundsChanged = null;
		internal void RaisePaintBoundsChanged()
		{
			OnPaintBoundsChanged(EventArgs.Empty);
		}

		internal DesignerStatus Status
		{
			get
			{
				if ( this.DesignerViewControl == null )
					return null;
				return this.DesignerViewControl.Status;
			}
		}

		internal SelectionFrame SelectionFrame
		{
			get { return _selectionFrame; }
			set
			{
				_selectionFrame = value;
			}
		}
		internal void ReleaseFocus()
		{
			_bFocused = false;
			OnLostFocus(EventArgs.Empty);
			Repaint();
		}

		internal void controls_ControlAdded(DesignerControl ctrl)
		{
			this.ChildPaintBoundsChanged += ctrl.RaisePaintBoundsChanged;

			ctrl.MouseEnter += new EventHandler(childCtrl_MouseEnter);
			ctrl.MouseLeave += new EventHandler(childCtrl_MouseLeave);

			OnControlAdded(ctrl);
		}
		internal void controls_ControlRemoved(DesignerControl ctrl)
		{
			this.ChildPaintBoundsChanged -= ctrl.RaisePaintBoundsChanged;

			ctrl.MouseEnter -= new EventHandler(childCtrl_MouseEnter);
			ctrl.MouseLeave -= new EventHandler(childCtrl_MouseLeave);

			OnControlRemoved(ctrl);
		}

		internal void InvokeMouseEnter(EventArgs e)
		{
			handleMouseEnter(e);
		}
		internal void InvokeMouseMove(MouseEventArgs e)
		{
			if ( !this.Visible || !this.Enabled )
				return;
			lock ( lockThis ) {
				//e = applyZoomFactor(e);
				if ( this is Route || this.Status.MouseOverCtrl == null || this.Status.MouseOverCtrl == this ||
					 this.Status.MouseOverCtrl == this.Parent ||
					 ( this.Status.CaptureControl != null || this.Status.CaptureControl == this )
					 && !bMouseOverChild ) {
					handleMouseMove(e);
				}
				if ( this.SelectionFrame != null && this.DesignerViewControl.Status.FocusedContol == this )
					this.SelectionFrame.InvokeMouseMove(e);
			}
		}
		internal void InvokeMouseLeave(EventArgs e)
		{
			handleMouseLeave(e);
		}
		internal void InvokeMouseDown(MouseEventArgs e)
		{
			if ( !this.Visible || !this.Enabled )
				return;
			//e = applyZoomFactor(e);
			if ( this.Status.MouseOverCtrl == this &&
				 ( this.DesignerViewControl.Status.CaptureControl == null ||
				   this.DesignerViewControl.Status.CaptureControl == this ) ) {
				handleMouseDown(e);
				if ( this.SelectionFrame != null )
					this.SelectionFrame.InvokeMouseDown(e);
			}
		}
		internal void InvokeMouseUp(MouseEventArgs e)
		{
			if ( !this.Visible || !this.Enabled ) return;
			//e = applyZoomFactor(e);
			if ( this.Status != null && ( this.Status.MouseOverCtrl == this ||
				 ( this.DesignerViewControl.Status.CaptureControl == null ||
				   this.DesignerViewControl.Status.CaptureControl == this ) ) ) {
				handleMouseUp(e);
				if ( this.SelectionFrame != null )
					this.SelectionFrame.InvokeMouseUp(e);
			}
		}
		internal void InvokeMouseClick(MouseEventArgs e)
		{
			if ( !this.Visible || !this.Enabled )
				return;
			//e = applyZoomFactor(e);
			if ( this.Status.MouseOverCtrl == this &&
				 ( this.DesignerViewControl.Status.CaptureControl == null ||
				   this.DesignerViewControl.Status.CaptureControl == this ) )
				handleMouseClick(e);
		}
		internal void InvokeMouseDoubleClick(MouseEventArgs e)
		{
			if ( !this.Visible || !this.Enabled )
				return;
			//e = applyZoomFactor(e);
			if ( this.Status.MouseOverCtrl == this &&
				 ( this.DesignerViewControl.Status.CaptureControl == null ||
				   this.DesignerViewControl.Status.CaptureControl == this ) )
				handleMouseDoubleClick(e);
		}

		internal DesignerControl GetTopMostChildAtDesignerViewPoint(Point location)
		{
			DesignerControl dc = this;
			for ( int i = this.Controls.Count - 1; i >= 0; i-- ) {
				using ( Region region = this.Controls[i].GetMouseOverArea() ) {
					if ( this.Controls[i].Visible && region.IsVisible(location) ) {
						dc = this.Controls[i].GetTopMostChildAtDesignerViewPoint(location);
						break;
					}
				}
			}
			return dc;
		}

		#endregion

		#region Protected Members

		#region Variables

		protected bool bMouseOver;
		protected bool bMouseOverChild;

		protected Guid guidIdentifier;

		#endregion

		#region Locking
		protected object lockThis = new object();
		protected static object lockAll = new object();
		#endregion

		#region Properties
		protected bool IsMouseOver
		{
			get { return bMouseOver; }
		}

		protected virtual Brush ForeBrush
		{
			get { return _foreSolidBrush; }
		}
		protected virtual Brush BackBrush
		{
			get { return _backSolidBrush; }
		}

		#endregion

		#region Methods

		protected static void dispose(object obj)
		{
			if ( obj == null )
				return;
			try {
				if ( obj is IDisposable ) {
					( (IDisposable)obj ).Dispose();
				}
			} catch ( Exception ex ) {
				Debug.WriteLine(ex.ToString());
			} finally {
				obj = null;
			}
		}

		protected virtual void OnTextChanged(EventArgs e)
		{
			EventHandler tmp = this.TextChanged;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnLocationChanged(EventArgs e)
		{
			DelegatePaintBoundsChanged del = this.ChildPaintBoundsChanged;
			if ( del != null )
				del();
			EventHandler tmp = this.LocationChanged;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnSizeChanged(EventArgs e)
		{
			DelegatePaintBoundsChanged del = this.ChildPaintBoundsChanged;
			if ( del != null )
				del();
			EventHandler tmp = this.SizeChanged;
			if ( tmp != null )
				tmp(this, e);
		}

		protected virtual void OnParentChanged(EventArgs e)
		{
			EventHandler tmp = this.ParentChanged;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnDesignerViewChanged(EventArgs e)
		{
			EventHandler tmp = this.DesignerViewChanged;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnModeChanged(EventArgs e)
		{
		}

		protected virtual void OnGotFocus(EventArgs e)
		{
			EventHandler tmp = this.GotFocus;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnLostFocus(EventArgs e)
		{
			EventHandler tmp = this.LostFocus;
			if ( tmp != null )
				tmp(this, e);
		}

		protected virtual void OnBackColorChanged(EventArgs e)
		{
			EventHandler tmp = this.BackColorChanged;
			if ( tmp != null )
				tmp(this, e);
			Invalidate();
			Update();
		}

		protected virtual void OnPaintBoundsChanged(EventArgs e)
		{
			DelegatePaintBoundsChanged del = this.ChildPaintBoundsChanged;
			if ( del != null )
				del();
			CalculateSpecialBounds();
			EventHandler tmp = this.PaintBoundsChanged;
			if ( tmp != null )
				tmp(this, e);
		}

		protected virtual void OnRemoving(CancelEventArgs e)
		{
			CancelEventHandler tmp = this.Removing;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnRemoved(EventArgs e)
		{
			EventHandler tmp = this.Removed;
			if ( tmp != null )
				tmp(this, e);
		}

		// Mouse Events
		protected virtual void OnMouseEnter(EventArgs e)
		{
			EventHandler tmp = this.MouseEnter;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseMove(MouseEventArgs e)
		{
			MouseEventHandler tmp = this.MouseMove;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseDown(MouseEventArgs e)
		{
			MouseEventHandler tmp = this.MouseDown;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseUp(MouseEventArgs e)
		{
			MouseEventHandler tmp = this.MouseUp;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseClick(MouseEventArgs e)
		{
			MouseEventHandler tmp = this.MouseClick;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseDoubleClick(MouseEventArgs e)
		{
			MouseEventHandler tmp = this.MouseDoubleClick;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnMouseLeave(EventArgs e)
		{
			EventHandler tmp = this.MouseLeave;
			if ( tmp != null )
				tmp(this, e);
		}

		protected virtual void OnParentLocationChanged()
		{
			applyAnchor();
			CalculateSpecialBounds();
		}
		protected virtual void OnParentSizeChanged()
		{
			applyAnchor();
			CalculateSpecialBounds();
		}
		protected virtual void OnControlAdded(DesignerControl ctrl)
		{
		}
		protected virtual void OnControlRemoved(DesignerControl ctrl)
		{
		}

		protected virtual void OnVisibleChanged()
		{
			this.BeginUpdate();
			foreach ( DesignerControl dc in this.Controls ) {
				dc.Visible = this.Visible;
			}
			this.EndUpdate();
		}

		protected virtual void Repaint()
		{
			this.Invalidate();
			this.Update();
			//if ( this.DesignerViewControl != null ) {
			//    this.DesignerViewControl.Refresh();
			//    //Debug.WriteLine("Refresh! " + DateTime.Now.ToString());
			//}
		}

		protected virtual Rectangle CalculateClientArea()
		{
			return _bounds;
		}
		protected virtual Region GetMouseOverArea()
		{
			return new Region(_boundsMouse);
		}

		protected virtual Rectangle GetPaintClientArea()
		{
			//Rectangle rectPaint = CalculateClientArea();
			//if ( this.Parent != null )
			//    rectPaint = this.Parent.RectangleToDesignerView(rectPaint);
			//return rectPaint;
			return _boundsPaint;
		}

		protected virtual void SetBounds(int x, int y, int width, int height, BoundsSpecified specified)
		{
			this.BeginUpdate();
			this.Invalidate();
			bool bLocationChanged = false;
			bool bSizeChanged = false;
			if ( ( specified & BoundsSpecified.X ) > 0 ) {
				if ( _bounds.X != x )
					bLocationChanged = true;
				_bounds.X = x;
			}
			if ( ( specified & BoundsSpecified.Y ) > 0 ) {
				if ( _bounds.Y != y )
					bLocationChanged = true;
				_bounds.Y = y;
			}
			if ( ( specified & BoundsSpecified.Width ) > 0 ) {
				if ( width < 0 ) width = 0;
				if ( !MinimumSize.Equals(Size.Empty) && width < MinimumSize.Width )
					width = MinimumSize.Width;
				else if ( !MaximumSize.Equals(Size.Empty) && width > MaximumSize.Width )
					width = MaximumSize.Width;

				if ( _bounds.Width != width )
					bSizeChanged = true;
				_bounds.Width = width;
			}
			if ( ( specified & BoundsSpecified.Height ) > 0 ) {
				if ( height < 0 ) height = 0;
				if ( !MinimumSize.Equals(Size.Empty) && height < MinimumSize.Height )
					height = MinimumSize.Height;
				else if ( !MaximumSize.Equals(Size.Empty) && height > MaximumSize.Height )
					height = MaximumSize.Height;

				if ( _bounds.Height != height )
					bSizeChanged = true;
				_bounds.Height = height;
			}
			if ( this.DesignerViewControl != null && this.UseGrid ) {
				_bounds = this.DesignerViewControl.RectangleToGrid(_bounds);
				if ( this.GridOffset != SizeF.Empty )
					_bounds.Location = Point.Add(_bounds.Location, Size.Round(this.GridOffset));
			}

			if ( bLocationChanged || bSizeChanged ) {
				initAnchorPositions();
				CalculateSpecialBounds();
				this.Invalidate();
			}
			if ( bLocationChanged )
				OnLocationChanged(EventArgs.Empty);
			if ( bSizeChanged )
				OnSizeChanged(EventArgs.Empty);

			if ( bLocationChanged || bSizeChanged ) {
				CalculateSpecialBounds();
			}

			this.EndUpdate();
			//this.Refresh();
			//Debug.WriteLine(DateTime.Now.ToString("mm:ss.ffffff") + this.ToString() + ".SetBounds()");
		}

		protected virtual void PaintChildControls(PaintEventArgs pe)
		{
			List<DesignerControl> listNoClip = new List<DesignerControl>();
			Region regClip = pe.Graphics.Clip.Clone();
			Rectangle bounds = GetPaintBounds();
			Rectangle clip = Rectangle.Ceiling(RectangleF.Intersect(bounds, pe.Graphics.ClipBounds));
			pe.Graphics.Clip = new Region(clip);
			//pe.Graphics.Clip.Intersect(bounds);
			foreach ( DesignerControl ctrl in this.Controls ) {
				if ( ctrl.Visible ) {
					if ( ctrl.NoClip )
						listNoClip.Add(ctrl);
					else {
						Rectangle ctrlbounds = ctrl.GetPaintBounds();
						ctrlbounds.Inflate(5, 5);
						if ( pe.Graphics.Clip.IsVisible(ctrlbounds) ) {
							ctrl.PaintBackground(pe);
						}
						ctrl.Paint(pe);
					}
				}
			}
			pe.Graphics.Clip = regClip;
			foreach ( DesignerControl ctrl in listNoClip ) {
				ctrl.PaintBackground(pe);
				ctrl.Paint(pe);
			}
		}

		protected virtual void CalculateSpecialBounds()
		{
			_boundsPaint = this.CalculateClientArea();
			if ( this.SelectionFrame != null ) {
				_boundsMouse = this.SelectionFrame.Bounds;
			} else {
				_boundsMouse = this.Bounds;
			}
			if ( this.Parent != null ) {
				_boundsPaint = this.Parent.RectangleToDesignerView(_boundsPaint);
				_boundsMouse = this.Parent.RectangleToDesignerView(_boundsMouse);
			}
		}

		protected Point ApplyZoomFactor(Point p)
		{
			Point point;
			if ( this.DesignerViewControl != null ) {
				float zoom = this.DesignerViewControl.ZoomFactor;
				if ( zoom != 1.0f )
					point = new Point((int)Math.Floor(p.X * zoom), (int)Math.Floor(p.Y * zoom));
				else
					point = p;
			} else {
				point = p;
			}
			return point;
		}
		protected Rectangle ApplyZoomFactor(Rectangle r)
		{
			Rectangle rect;
			if ( this.DesignerViewControl != null ) {
				float zoom = this.DesignerViewControl.ZoomFactor;
				if ( zoom != 1.0f )
					rect = new Rectangle((int)Math.Floor(r.X * zoom), (int)Math.Floor(r.Y * zoom), (int)Math.Ceiling(r.Width * zoom), (int)Math.Ceiling(r.Height * zoom));
				else
					rect = r;
			} else {
				rect = r;
			}
			return rect;
		}

		#endregion

		#endregion

		#region Private Members

		#region Constants
		#endregion

		#region Variables

		// uninitialized variables

		private bool _bEnabled;
		private bool _bVisible;
		private bool _bFocused;
		private bool _bSelected;
		private bool _bTabStop;
		private bool _bIsDisposed;
		private bool _bTopLevel;

		private int _iTabIndex;

		private string _name;
		private string _text;

		private Color _backColor1;
		private SolidBrush _backSolidBrush;

		private SolidBrush _foreSolidBrush;
		private Font _font;

		private object _tag;

		private Rectangle _bounds;
		private Rectangle _boundsPaint;
		private Rectangle _boundsMouse;
		private Size _maxSize;
		private Size _minSize;
		private Point _ptMouseDown;

		private volatile ContextMenuStrip _contextMenu;
		private volatile Cursor _cursor;
		private volatile Cursor _cursorBeforeOver;

		private volatile DesignerViewControl _designerView;
		private volatile DesignerControl _parent;
		private volatile DesignerControlCollection _controls;

		private volatile SelectionFrame _selectionFrame;

		private ISite _site;

		private ToolTip _toolTip;
		//private bool _showTooltip = false;

		// Anchor
		private AnchorStyles _anchor;
		private int _anchorTop;
		private int _anchorBottom;
		private int _anchorLeft;
		private int _anchorRight;

		// drag&drop
		private bool _bAllowDrop;
		#endregion

		#region Methods

		private string getDefaultName()
		{
			Type type = this.GetType();
			string name = type.Name;
			int count = 0;
			if ( name.Length > 0 ) {
				char first = name[0];
				name = name.Remove(0, 1);
				name = name.Insert(0, char.ToLower(first).ToString());
			}
			if ( _dicCounter.ContainsKey(type) ) {
				count = _dicCounter[type];
				count++;
				_dicCounter[type] = count;
			} else {
				count++;
				_dicCounter.Add(type, count);
			}
			name = name + count.ToString();
			return name;
		}

		private void doMaxSizeChanged()
		{
			this.BeginUpdate();
			if ( this.Size.Width > this.MaximumSize.Width )
				this.Width = this.MaximumSize.Width;
			if ( this.Size.Height > this.MaximumSize.Height )
				this.Height = this.MaximumSize.Height;
			this.EndUpdate();
		}
		private void doMinSizeChanged()
		{
			this.BeginUpdate();
			if ( this.Size.Width < this.MinimumSize.Width )
				this.Width = this.MaximumSize.Width;
			if ( this.Size.Height < this.MinimumSize.Height )
				this.Height = this.MaximumSize.Height;
			this.EndUpdate();
		}

		private bool getContainsFocus()
		{
			// TODO: get contains focus
			return false;
		}

		private void releaseParent()
		{
			// only if parent is not null
			if ( _parent != null ) {
				// save parent reference
				DesignerControl pctrl = _parent;
				// set parent to null to prevent infinite loops
				_parent = null;
				// unbind events
				pctrl.SizeChanged -= new EventHandler(parent_SizeChanged);
				pctrl.LocationChanged -= new EventHandler(parent_LocationChanged);
				// if parent contains this then remove this from parent
				if ( pctrl.Controls.Contains(this) )
					pctrl.Controls.Remove(this);
			}
		}
		private void doParentChanged()
		{
			//CalculateSpecialBounds();
			// only if parent is not null
			if ( _parent != null ) {
				// bind events
				_parent.SizeChanged += new EventHandler(parent_SizeChanged);
				_parent.LocationChanged += new EventHandler(parent_LocationChanged);
				// if parent doesn't contain this then add this to parent
				if ( !_parent.Controls.Contains(this) )
					_parent.Controls.Add(this);
				// if this designer view is null then set to parent designer view
				if ( _designerView != null ) {
					// if the designer view contains this then remove it
					if ( _designerView.DesignerControls.Contains(this) )
						_designerView.DesignerControls.Remove(this);
				}
				// if the designer view changed then set to parent designer view
				if ( _designerView != _parent.DesignerViewControl ) {
					_designerView = _parent.DesignerViewControl;
					// update designer view of child controls
					foreach ( DesignerControl ctrl in this.Controls ) {
						ctrl.DesignerViewControl = _designerView;
					}
				}

			}
			// initialize anchor
			doAnchorChanged();
			// fire paint bounds changed
			OnPaintBoundsChanged(EventArgs.Empty);
			// fire parent changed
			OnParentChanged(EventArgs.Empty);
			// repaint this
			Repaint();
		}

		private void releaseDesignerView()
		{
			// deselect
			this.Selected = false;
			// only if designer view is not null
			if ( _designerView != null ) {
				// save designer view reference
				DesignerViewControl view = _designerView;
				// set designer view to null to prevent infinite loops
				_designerView = null;
				// if designer view contains this then remove this from designer view
				if ( view.DesignerControls.Contains(this) )
					view.DesignerControls.Remove(this);
				view.DesignController.ModeChanged -= new EventHandler(DesignController_ModeChanged);
				OnModeChanged(EventArgs.Empty);
			}
			// remove designer view from child controls (recursive function)
			foreach ( DesignerControl ctrl in this.Controls ) {
				ctrl.DesignerViewControl = null;
			}
		}
		private void doDesignerViewChanged()
		{
			// only if designer view is not null
			if ( _designerView != null ) {
				// if parent is null and designer view  doesn't contain this then ass this to designer view
				if ( _parent == null && !_designerView.DesignerControls.Contains(this) )
					_designerView.DesignerControls.Add(this);
				// register events
				_designerView.DesignController.ModeChanged += new EventHandler(DesignController_ModeChanged);
				OnModeChanged(EventArgs.Empty);
			}
			foreach ( DesignerControl ctrl in this.Controls ) {
				ctrl.DesignerViewControl = this.DesignerViewControl;
			}
			OnDesignerViewChanged(EventArgs.Empty);
		}

		private void doTabIndexChanged()
		{
			Repaint();
		}
		private void doSelectionChanged()
		{
			if ( this.DesignerViewControl != null ) {
				this.BeginUpdate();
				if ( this.DesignerViewControl.SelectedControls.Contains(this) ) {
					// this control is in the selected controls collection
					if ( !_bSelected )
						this.DesignerViewControl.SelectedControls.Remove(this);
				} else {
					// this control is NOT in the selected controls collection
					if ( _bSelected )
						this.DesignerViewControl.SelectedControls.Add(this);
				}
				if ( _bSelected ) {
					if ( this.SelectionFrame == null )
						this.SelectionFrame = new SelectionFrame(this);
				} else {
					if ( this.SelectionFrame != null ) {
						this.SelectionFrame.Dispose();
						this.SelectionFrame = null;
					}
				}
				CalculateSpecialBounds();
				this.EndUpdate();
			}
		}

		private void doAnchorChanged()
		{
			initAnchorPositions();
		}
		private void initAnchorPositions()
		{
			_anchorTop = this.Top;
			_anchorBottom = ( this.Parent != null ? this.Parent.ClientRectangle.Bottom - this.Bottom : this.Bottom );
			_anchorLeft = this.Left;
			_anchorRight = ( this.Parent != null ? this.Parent.ClientRectangle.Right - this.Right : this.Right );
		}
		private void applyAnchor()
		{
			if ( this.Parent == null )
				return;
			int l, r, t, b, c; // l=left, r=right, t=top, b=bottom, c=center
			Rectangle rectNew;
			Rectangle rectParent = this.Parent.ClientRectangle;
			lock ( lockThis ) {
				l = _anchorLeft;
				t = _anchorTop;
				r = rectParent.Right - _anchorRight;
				b = rectParent.Bottom - _anchorBottom;
				if ( ( this._anchor & ( AnchorStyles.Left | AnchorStyles.Right ) ) == 0 ) {
					c = l + ( ( r - l ) / 2 );
					l = c - ( this.Width / 2 );
					r = l + this.Width;
				} else if ( ( this.Anchor & AnchorStyles.Left ) == 0 ) {
					l = r - this.Width;
				} else if ( ( this.Anchor & AnchorStyles.Right ) == 0 ) {
					r = l + this.Width;
				}
				if ( ( this._anchor & ( AnchorStyles.Top | AnchorStyles.Bottom ) ) == 0 ) {
					c = t + ( ( b - t ) / 2 );
					t = c - ( this.Height / 2 );
					b = t + this.Height;
				} else if ( ( this.Anchor & AnchorStyles.Top ) == 0 ) {
					t = b - this.Height;
				} else if ( ( this.Anchor & AnchorStyles.Bottom ) == 0 ) {
					b = t + this.Height;
				}
				rectNew = Rectangle.FromLTRB(l, t, r, b);
			}
			this.Bounds = rectNew;
			//initAnchorPositions();
		}

		private void doTextChanged()
		{
			OnTextChanged(EventArgs.Empty);
		}
		private void doBackColor1Changed()
		{
			if ( _backSolidBrush == null )
				_backSolidBrush = new SolidBrush(_backColor1);
			else
				_backSolidBrush.Color = _backColor1;
			//foreach ( DesignerControl c in this.Controls ) {
			//    c.BackColor = this.BackColor;
			//}
			OnBackColorChanged(EventArgs.Empty);
		}
		private void doForeColorChanged()
		{
			foreach ( DesignerControl c in this.Controls ) {
				c.ForeColor = this.ForeColor;
			}
			Repaint();
		}
		private void doFontChanged()
		{
			foreach ( DesignerControl c in this.Controls ) {
				c.Font = this.Font;
			}
			Repaint();
		}

		private void doShowContextMenu(MouseEventArgs e)
		{
			Point loc = e.Location;
			if ( this.DesignerViewControl != null ) {
				float zoom = this.DesignerViewControl.ZoomFactor;
				loc = new Point((int)Math.Floor(loc.X * zoom), (int)Math.Floor(loc.Y * zoom));
			}
			this.ContextMenuStrip.Show(this.DesignerViewControl.MainPanel, loc);
		}

		private void handleMouseEnter(EventArgs e)
		{
			// Mouse entered this
			if ( Status.CurrentMouseMoveMode == MouseMoveMode.Normal ) {
				_cursorBeforeOver = this.DesignerViewControl.Cursor;
				this.DesignerViewControl.Cursor = this.Cursor;
			}
			this.Status.MouseOverCtrl = this;
			OnMouseEnter(e);
			//_showTooltip = true;
			bMouseOver = true;
		}
		private void handleMouseMove(MouseEventArgs e)
		{
			if ( e == null ) return;

			//if ( _toolTip != null && this.DesignerViewControl != null ) {
			//    if ( _showTooltip ) {
			//        Point pt3 = DesignerViewControl.PointToScreen(e.Location);		
			//        pt3 = this.DesignerViewControl.TopLevelControl.PointToClient(pt3);
			//        _toolTip.Show(ToolText, this.DesignerViewControl.TopLevelControl, pt3);
			//        //_showTooltip = false;
			//    }
			//}
			if ( this.DesignerViewControl != null ) {
				this.DesignerViewControl.SetToolText(this.ToolText);
			}
			lock ( lockThis ) {
				bool bOver = CheckMouseOver(e.Location);
				if ( bOver || ( this.Status != null && this.Status.CaptureControl == this ) ) {
					if ( bOver && this.Status.MouseOverCtrl == null ) {
						this.Status.MouseOverCtrl = this;
					}
					// Mouse over
					DesignerControl dc = this.GetChildAtPoint(this.PointToDesignerControlClient(e.Location));
					if ( dc != null ) {
						if ( dc.CanFocused ) this.Status.MouseOverCtrl = dc;
						dc.InvokeMouseMove(e);
					}
					if ( e.Button == MouseButtons.Right &&
						 ( this.Status.MouseOverCtrl == this || this.Status.CaptureControl == this ) ) {
						if ( this.Status.CurrentMouseMoveMode == MouseMoveMode.Normal ) {
							int movedX = _ptMouseDown.IsEmpty ? 0 : Math.Abs(e.Location.X - _ptMouseDown.X);
							int movedY = _ptMouseDown.IsEmpty ? 0 : Math.Abs(e.Location.Y - _ptMouseDown.Y);
							if ( this.CanDrag && ( movedX > 10 || movedY > 10 ) ) {
								setCursor(Cursors.Default);
								this.Status.CurrentMouseMoveMode = MouseMoveMode.DragDrop;
								this.Status.DragObject = this.GetDragObject(e.Location, e.Button);
							}
						} else if ( this.Status.CurrentMouseMoveMode == MouseMoveMode.DragDrop ) {
							if ( this.Status.MouseOverCtrl != null &&
								 this.Status.MouseOverCtrl.IsDropAllowed(
									this.Status.DragObject, e.Location, e.Button) ) {
								setCursor(Cursors.Default);
							} else {
								setCursor(Cursors.No);
							}
							//string txt = ( this.Status.DragObject is DesignerControl ?
							//    ( (DesignerControl)this.Status.DragObject ).Text : this.Status.DragObject.ToString() );
							Point pDDtxt = e.Location + new Size(20, 20);
							Rectangle r = new Rectangle(pDDtxt, new Size(200, 30));
							r.Inflate(10, 10);
							this.DesignerViewControl.MainPanel.Invalidate(r, true);
							this.DesignerViewControl.Refresh();
							//Repaint();
						}
					}
					OnMouseMove(e);
				}
			}
		}
		private void handleMouseLeave(EventArgs e)
		{
			_ptMouseDown = Point.Empty;
			// Mouse leaved this
			if ( Status.CurrentMouseMoveMode == MouseMoveMode.Normal ) {
				this.DesignerViewControl.Cursor = _cursorBeforeOver;
			}
			this.Status.MouseOverCtrl = null;
			OnMouseLeave(e);
			bMouseOver = false;
			//_showTooltip = true;
			//if ( _toolTip != null && DesignerViewControl != null ) {
			//    _toolTip.Hide(DesignerViewControl);
			//}
			this.DesignerViewControl.SetToolText(null);
		}
		private void handleMouseDown(MouseEventArgs e)
		{
			_ptMouseDown = e.Location;
			this.Status.CaptureControl = this;
			if ( !this.Focused && this.CanFocused ) Focus();

			if ( this.Selected ) {
				DesignerControl dc = this.GetChildAtPoint(this.PointToDesignerControlClient(e.Location));
				if ( dc != null ) dc.InvokeMouseDown(e);
			} else {
				if ( this.CanSelect ) {
					Select();
				} else if ( this.Parent != null ) {
					this.Parent.Select();
				}
			}
			OnMouseDown(e);
		}
		private void handleMouseUp(MouseEventArgs e)
		{
			_ptMouseDown = Point.Empty;
			this.Status.CaptureControl = null;
			if ( this.Status.CurrentMouseMoveMode == MouseMoveMode.DragDrop ) {
				this.BeginUpdate();
				if ( this.Status.MouseOverCtrl != null &&
					 this.Status.MouseOverCtrl.IsDropAllowed(this.Status.DragObject, e.Location, e.Button) ) {
					this.Status.MouseOverCtrl.DropObject(this.Status.DragObject, e.Location, e.Button);
				}
				//Repaint();
				this.Status.CurrentMouseMoveMode = MouseMoveMode.Normal;
				this.Status.DragObject = null;
				this.DesignerViewControl.Cursor = Cursors.Default;
				this.EndUpdate();
			}
			OnMouseUp(e);
		}
		private void handleMouseClick(MouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Right && this.ContextMenuStrip != null &&
				 this.Status.CurrentMouseMoveMode != MouseMoveMode.DragDrop ) {
				doShowContextMenu(e);
			}
			OnMouseClick(e);
		}
		private void handleMouseDoubleClick(MouseEventArgs e)
		{
			OnMouseDoubleClick(e);
		}

		private MouseEventArgs applyZoomFactor(MouseEventArgs e)
		{
			MouseEventArgs newMEA;
			if ( this.DesignerViewControl != null ) {
				float zoom = this.DesignerViewControl.ZoomFactor;
				if ( zoom != 1.0f )
					newMEA = new MouseEventArgs(e.Button, e.Clicks, (int)Math.Floor(e.X * zoom), (int)Math.Floor(e.Y * zoom), e.Delta);
				else
					newMEA = e;
			} else {
				newMEA = e;
			}
			return newMEA;
		}
		private void setCursor(Cursor cur)
		{
			if ( this.DesignerViewControl.InvokeRequired ) {
				setControlProperty(this.DesignerViewControl, "Cursor", cur);
			} else {
				this.DesignerViewControl.Cursor = cur;
			}
		}

		private delegate void SetValueDelegate(Object obj, Object val, Object[] index);
		private void setControlProperty(Control ctrl, String propName, Object val)
		{
			PropertyInfo propInfo = ctrl.GetType().GetProperty(propName);
			Delegate dgtSetValue = new SetValueDelegate(propInfo.SetValue);
			ctrl.Invoke(dgtSetValue, new Object[3] { ctrl, val, /*index*/null });
		}

		#endregion

		#region Event Handlers

		#region Mouse Events (Disabled)
		//private void _designerView_MouseMove(object sender, MouseEventArgs e)
		//{
		//    if ( !this.Visible || !this.Enabled )
		//        return;
		//    e = applyZoomFactor(e);
		//    if ( this is Route || this.Status.MouseOverCtrl == null || this.Status.MouseOverCtrl == this ||
		//         this.Status.MouseOverCtrl == this.Parent ||
		//         (this.Status.CaptureControl != null || this.Status.CaptureControl == this )
		//         && !bMouseOverChild ) {
		//        handleMouseMove(e);
		//    }
		//    if ( this.SelectionFrame != null && this.DesignerViewControl.Status.FocusedContol == this )
		//        this.SelectionFrame.InvokeMouseMove(e);
		//}
		//private void _designerView_MouseDown(object sender, MouseEventArgs e)
		//{
		//    if ( !this.Visible || !this.Enabled )
		//        return;
		//    e = applyZoomFactor(e);
		//    if ( this.Status.MouseOverCtrl == this &&
		//         ( this.DesignerViewControl.Status.CaptureControl == null ||
		//           this.DesignerViewControl.Status.CaptureControl == this ) ) {
		//        handleMouseDown(e);
		//        if ( this.SelectionFrame != null )
		//            this.SelectionFrame.InvokeMouseDown(e);
		//    }
		//}
		//private void _designerView_MouseUp(object sender, MouseEventArgs e)
		//{
		//    if ( !this.Visible || !this.Enabled )
		//        return;
		//    e = applyZoomFactor(e);
		//    if (this.Status != null && (this.Status.MouseOverCtrl == this ||
		//         ( this.DesignerViewControl.Status.CaptureControl == null ||
		//           this.DesignerViewControl.Status.CaptureControl == this )) ) {
		//        handleMouseUp(e);
		//        if ( this.SelectionFrame != null )
		//            this.SelectionFrame.InvokeMouseUp(e);
		//    }
		//}
		//private void _designerView_MouseClick(object sender, MouseEventArgs e)
		//{
		//    if ( !this.Visible || !this.Enabled )
		//        return;
		//    e = applyZoomFactor(e);
		//    if ( this.Status.MouseOverCtrl == this &&
		//         ( this.DesignerViewControl.Status.CaptureControl == null ||
		//           this.DesignerViewControl.Status.CaptureControl == this ) )
		//        handleMouseClick(e);
		//}
		//private void _designerView_MouseDoubleClick(object sender, MouseEventArgs e)
		//{
		//    if ( !this.Visible || !this.Enabled )
		//        return;
		//    e = applyZoomFactor(e);
		//    if ( this.Status.MouseOverCtrl == this &&
		//         ( this.DesignerViewControl.Status.CaptureControl == null ||
		//           this.DesignerViewControl.Status.CaptureControl == this ) )
		//        handleMouseDoubleClick(e);
		//}

		#endregion

		private void childCtrl_MouseLeave(object sender, EventArgs e)
		{
			bMouseOverChild = false;
			handleMouseMove(e as MouseEventArgs);
		}
		private void childCtrl_MouseEnter(object sender, EventArgs e)
		{
			bMouseOverChild = true;
			bMouseOver = false;
		}

		private void parent_LocationChanged(object sender, EventArgs e)
		{
			OnParentLocationChanged();
		}
		private void parent_SizeChanged(object sender, EventArgs e)
		{
			OnParentSizeChanged();
		}

		private void context_Remove(object sender, EventArgs e)
		{
			if ( MessageBox.Show(
					string.Format(Resources.msgRemoveDesignerControl, this.Text),
					this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes ) {
				this.Remove();
			}
		}

		private void DesignController_ModeChanged(object sender, EventArgs e)
		{
			OnModeChanged(e);
		}

		#endregion

		#endregion

		#region Class: DesignerControlCollection
		public class DesignerControlCollection : CollectionBase
		{
			#region Initialization
			public DesignerControlCollection(DesignerControl owner)
			{
				_owner = owner;
			}
			#endregion

			#region Properties
			public DesignerControl this[int index]
			{
				get
				{
					return ( (DesignerControl)List[index] );
				}
				set
				{
					if ( !noRecursion(value, _owner) )
						return;
					List[index] = value;
				}
			}
			#endregion

			#region Methods
			public int Add(DesignerControl value)
			{
				if ( !noRecursion(value, _owner) )
					return -1;

				// if collection contains the value then return the index of the value
				if ( InnerList.Contains(value) )
					return InnerList.IndexOf(value);

				return ( List.Add(value) );
			}
			public void AddRange<T>(IEnumerable<T> controls) where T : DesignerControl
			{
				foreach ( DesignerControl ctrl in controls ) {
					this.Add(ctrl);
				}
			}
			public int IndexOf(DesignerControl value)
			{
				return ( List.IndexOf(value) );
			}
			public void Insert(int index, DesignerControl value)
			{
				if ( !noRecursion(value, _owner) )
					return;

				// if collection contains the value then first remove it from the InnerList
				// because the OnRemove is not called
				if ( InnerList.Contains(value) )
					InnerList.Remove(value);

				List.Insert(index, value);
			}
			public void Remove(DesignerControl value)
			{
				List.Remove(value);
			}
			public bool Contains(DesignerControl value)
			{
				// If value is not of type DesignerControl, this will return false.
				return ( List.Contains(value) );
			}

			public DesignerControl[] ToArray()
			{
				return (DesignerControl[])this.InnerList.ToArray(typeof(DesignerControl));
			}

			protected override void OnInsert(int index, Object value)
			{
				if ( !( value is DesignerControl ) )
					throw new ArgumentException("value must be of type DesignerControl.", "value");
			}
			protected override void OnRemove(int index, Object value)
			{
				if ( !( value is DesignerControl ) )
					throw new ArgumentException("value must be of type DesignerControl.", "value");
			}
			protected override void OnSet(int index, Object oldValue, Object newValue)
			{
				if ( !( oldValue is DesignerControl ) )
					throw new ArgumentException("oldValue must be of type DesignerControl.", "oldValue");
				if ( !( newValue is DesignerControl ) )
					throw new ArgumentException("newValue must be of type DesignerControl.", "newValue");
			}
			protected override void OnValidate(Object value)
			{
				if ( !( value is DesignerControl ) )
					throw new ArgumentException("value must be of type DesignerControl.", "value");
			}

			protected override void OnClearComplete()
			{
				refreshOwner();
				base.OnClearComplete();
			}
			protected override void OnInsertComplete(int index, object value)
			{
				DesignerControl dc = (DesignerControl)value;
				dc.Parent = _owner;
				dc.Site = _owner.Site;
				//dc.DesignerViewControl = _owner.DesignerViewControl;
				if ( dc.DesignerViewControl != null && dc.UseGrid )
					dc.Location = _owner.DesignerViewControl.PointToGrid(dc.Location);
				_owner.controls_ControlAdded(dc);

				refreshOwner();

				base.OnInsertComplete(index, value);
			}
			protected override void OnRemoveComplete(int index, object value)
			{
				DesignerControl dc = (DesignerControl)value;
				dc.Parent = null;
				//dc.DesignerViewControl = null;
				_owner.controls_ControlRemoved(dc);

				refreshOwner();

				base.OnRemoveComplete(index, value);
			}
			protected override void OnSetComplete(int index, object oldValue, object newValue)
			{
				DesignerControl dc;

				dc = (DesignerControl)oldValue;
				dc.Parent = null;
				//dc.DesignerViewControl = null;
				_owner.controls_ControlRemoved(dc);

				dc = (DesignerControl)newValue;
				dc.Parent = _owner;
				dc.Site = _owner.Site;
				//dc.DesignerViewControl = _owner.DesignerViewControl;
				if ( dc.UseGrid )
					dc.Location = _owner.DesignerViewControl.PointToGrid(dc.Location);
				_owner.controls_ControlAdded(dc);

				refreshOwner();

				base.OnSetComplete(index, oldValue, newValue);
			}

			private void refreshOwner()
			{
				if ( _owner != null )
					_owner.Refresh();
			}
			private bool noRecursion(DesignerControl dc, DesignerControl current)
			{
				if ( dc == current.Parent )
					return false;
				else if ( current.Parent == null )
					return true;
				else
					return noRecursion(dc, current.Parent);
			}
			#endregion

			#region Private Variables

			private DesignerControl _owner = null;

			#endregion
		}
		#endregion

		#region Class: DesignerControlEventArgs
		public class DesignerControlEventArgs : EventArgs
		{
			#region Initialization
			public DesignerControlEventArgs(DesignerControl ctrl)
			{
				_ctrl = ctrl;
			}
			#endregion

			#region Properties
			private readonly DesignerControl _ctrl;
			public DesignerControl Control
			{
				get { return _ctrl; }
			}

			#endregion

			#region Methods
			#endregion
		}
		#endregion


		#region IEquatable<Route> Members

		public bool Equals(Route other)
		{
			return ( other != null && other.guidIdentifier == this.guidIdentifier );
		}

		#endregion
	}
}
